package irc
import (
	"bytes"
	"encoding/binary"
	"io"
	"ircove.com/common"
	"log"
)
//消息类型
type MessageType uint8
const (
	MessageType_CTRL      = MessageType(iota + 1) //控制
	MessageType_RPC                               //RPC
	MessageType_Hub                               //订阅发布
	MessageType_HeartBeat                         //心跳
	messagetype_max                               //判断使用
)
const (
	HasMessageID  = byte(0x08)
	HasMessageLen = byte(0x04)
)

//type MessageFormat   byte

const (
	MessageFormat_Custom = uint8(iota)
	MessageFormat_JSON
	MessageFormat_MSGPACK
	MessageFormat_PROTOBUF
)
type Header struct {
	MessageType   MessageType
	MessageFormat uint8
	HasMessageID  bool
	HasMessageLen bool
	MessageID     uint16
	MessageLen    uint16
}

func (this *Header) Decode(r io.Reader) error {
	var buf [1]byte
	if _, err := io.ReadFull(r, buf[:]); err != nil {
		return common.NetWorkError
	}
	byte1 := buf[0]
	msgtype := MessageType(byte1 & 0xF0 >> 4)
	hasmessageid := byte1&HasMessageID == HasMessageID
	hasmessagelen := byte1&HasMessageLen == HasMessageLen

	if hasmessageid {
		msgid, err := Read_uint16(r)
		if err != nil || msgid < 1 {
			return common.ErrorArgument
		}
		this.MessageID = msgid
	}
	if hasmessagelen {
		msglen, err := Read_uint16(r)
		if err != nil || msglen < 1 {
			return common.ErrorArgument
		}
		this.MessageLen = msglen
	}

	this.MessageFormat = byte1 & 0x03
	this.MessageType = msgtype
	this.HasMessageID = hasmessageid
	this.HasMessageLen = hasmessagelen
	return nil
}

func (this *Header) Encode(w io.Writer) error {
	buf := new(bytes.Buffer)
	val := byte(this.MessageType << 4)
	if this.HasMessageID || this.MessageID > 0 {
		val |= HasMessageID
	} else {
		this.HasMessageID = false
	}
	if this.HasMessageLen || this.MessageLen > 0 {
		val |= HasMessageLen
	} else {
		this.HasMessageLen = false
	}
	val |= this.MessageFormat

	err := buf.WriteByte(val)

	if this.HasMessageID {
		if err = binary.Write(buf, binary.BigEndian, this.MessageID); err != nil {
			log.Fatal(err)
			return common.NetWorkError
		}
		//Write_uint16(hdr.MessageID,buf)
	}
	if this.HasMessageLen {
		if err = binary.Write(buf, binary.BigEndian, this.MessageLen); err != nil {
			log.Fatal(err)
			return common.NetWorkError
		}
	}
	_, err = w.Write(buf.Bytes())
	return err
}

func (this *Header) SetMessageLen(len int) error {

	if len >= 65535 {
		log.Println("message data is to long!")
		return common.ErrorArgument
	}
	if len > 0 {
		this.HasMessageLen = true
		this.MessageLen = uint16(len)
	}
	return nil
}

func (this *Header) SetMessageID(len int) error {
	if len >= 65535 {
		log.Println("message data is to long!")
		return common.ErrorArgument
	}
	if len > 0 {
		this.HasMessageID = true
		this.MessageID = uint16(len)
	}
	return nil
}

